home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Tool Chest / Development Tools & Languages / • Other Platforms / PCCTS 1.31 / antlr / gen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-10  |  60.3 KB  |  2,516 lines  |  [TEXT/MPS ]

  1. /*
  2.  * gen.c
  3.  *
  4.  * $Id: gen.c,v 1.15 1994/12/31 21:02:55 parrt Exp parrt $
  5.  * $Revision: 1.15 $
  6.  *
  7.  * Generate C code (ANSI, K&R, C++)
  8.  *
  9.  * SOFTWARE RIGHTS
  10.  *
  11.  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
  12.  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
  13.  * company may do whatever they wish with source code distributed with
  14.  * PCCTS or the code generated by PCCTS, including the incorporation of
  15.  * PCCTS, or its output, into commerical software.
  16.  *
  17.  * We encourage users to develop software with PCCTS.  However, we do ask
  18.  * that credit is given to us for developing PCCTS.  By "credit",
  19.  * we mean that if you incorporate our source code into one of your
  20.  * programs (commercial product, research project, or otherwise) that you
  21.  * acknowledge this fact somewhere in the documentation, research report,
  22.  * etc...  If you like PCCTS and have developed a nice tool with the
  23.  * output, please mention that you developed it using PCCTS.  In
  24.  * addition, we ask that this header remain intact in our source code.
  25.  * As long as these guidelines are kept, we expect to continue enhancing
  26.  * this system and expect to make other tools available as they are
  27.  * completed.
  28.  *
  29.  * ANTLR 1.31
  30.  * Terence Parr
  31.  * Parr Research Corporation
  32.  * with Purdue University and AHPCRC, University of Minnesota
  33.  * 1989-1995
  34.  */
  35. #include <stdio.h>
  36. #include <ctype.h>
  37. #include "set.h"
  38. #include "syn.h"
  39. #include "hash.h"
  40. #include "generic.h"
  41. #include "dlgdef.h"
  42.  
  43. #define NumExprPerLine    4
  44. static int on1line=0;
  45. static set tokensRefdInBlock;
  46.  
  47.  
  48.                     /* T r a n s l a t i o n  T  
  49. a b l e s */
  50.  
  51. /* C_Trans[node type] == pointer to function that knows how to translate that node. */
  52. #ifdef __cplusplus
  53. void (*C_Trans[NumNodeTypes+1])(...) = {
  54.     NULL,
  55.     NULL,                    /* See next table.   
  56. Junctions have many types */
  57.     (void (*)(...)) genRuleRef,
  58.     (void (*)(...)) genToken,
  59.     (void (*)(...)) genAction
  60. };
  61. #else
  62. void (*C_Trans[NumNodeTypes+1])() = {
  63.     NULL,
  64.     NULL,                    /* See next table.   
  65. Junctions have many types */
  66.     genRuleRef,
  67.     genToken,
  68.     genAction
  69. };
  70. #endif
  71.  
  72. /* C_JTrans[Junction type] == pointer to function that knows how to translate that
  73.  * kind of junction node.
  74.  */
  75. #ifdef __cplusplus
  76. void (*C_JTrans[NumJuncTypes+1])(...) = {
  77.     NULL,
  78.     (void (*)(...)) genSubBlk,
  79.     (void (*)(...)) genOptBlk,
  80.     (void (*)(...)) genLoopBlk,
  81.     (void (*)(...)) genEndBlk,
  82.     (void (*)(...)) genRule,
  83.     (void (*)(...)) genJunction,
  84.     (void (*)(...)) genEndRule,
  85.     (void (*)(...)) genPlusBlk,
  86.     (void (*)(...)) genLoopBegin
  87. };
  88. #else
  89. void (*C_JTrans[NumJuncTypes+1])() = {
  90.     NULL,
  91.     genSubBlk,
  92.     genOptBlk,
  93.     genLoopBlk,
  94.     genEndBlk,
  95.     genRule,
  96.     genJunction,
  97.     genEndRule,
  98.     genPlusBlk,
  99.     genLoopBegin
  100. };
  101. #endif
  102.  
  103. #define PastWhiteSpace(s)    while (*(s) == ' ' || *(s) == '\t') {s++;}
  104.  
  105. static int tabs = 0;
  106. #define TAB { int i; for (i=0; i<tabs; i++) fputc('\t', output); }
  107. static void
  108. #ifdef __USE_PROTOS
  109. tab( void )
  110. #else
  111. tab( )
  112. #endif
  113. TAB
  114.  
  115. #ifdef __USE_PROTOS
  116. static char *tokenFollowSet(TokNode *);
  117. static ActionNode *findImmedAction( Node * );
  118. static void dumpRetValAssign(char *, char *);
  119. static void dumpAfterActions(FILE *output);
  120. static set ComputeErrorSet(Junction *, int);
  121. static void makeErrorClause(Junction *, set, int);
  122. static void DumpFuncHeader( Junction *, RuleEntry * );
  123. static int has_guess_block_as_first_item(Junction *);
  124. static int genExprSets(set *, int);
  125. static void genExprTree( Tree *t, int k );
  126. #else
  127. static char *tokenFollowSet();
  128. static ActionNode *findImmedAction();
  129. static void dumpRetValAssign();
  130. static void dumpAfterActions();
  131. static set ComputeErrorSet();
  132. static void makeErrorClause();
  133. static void DumpFuncHeader();
  134. static int has_guess_block_as_first_item();
  135. static int genExprSets();
  136. static void genExprTree();
  137. #endif
  138.  
  139. #define gen(s)            {tab(); fprintf(output, s);}
  140. #define gen1(s,a)        {tab(); fprintf(output, s,a);}
  141. #define gen2(s,a,b)        {tab(); fprintf(output, s,a,b);}
  142. #define gen3(s,a,b,c)    {tab(); fprintf(output, s,a,b,c);}
  143. #define gen4(s,a,b,c,d)    {tab(); fprintf(output, s,a,b,c,d);}
  144. #define gen5(s,a,b,c,d,e)    {tab(); fprintf(output, s,a,b,c,d,e);}
  145. #define gen6(s,a,b,c,d,e,f)    {tab(); fprintf(output, s,a,b,c,d,e,f);}
  146. #define gen7(s,a,b,c,d,e,f,g)    {tab(); fprintf(output, s,a,b,c,d,e,f,g);}
  147.  
  148. #define _gen(s)            {fprintf(output, s);}
  149. #define _gen1(s,a)        {fprintf(output, s,a);}
  150. #define _gen2(s,a,b)    {fprintf(output, s,a,b);}
  151. #define _gen3(s,a,b,c)    {fprintf(output, s,a,b,c);}
  152. #define _gen4(s,a,b,c,d){fprintf(output, s,a,b,c,d);}
  153. #define _gen5(s,a,b,c,d,e){fprintf(output, s,a,b,c,d,e);}
  154. #define _gen6(s,a,b,c,d,e,f){fprintf(output, s,a,b,c,d,e,f);}
  155. #define _gen7(s,a,b,c,d,e,f,g){fprintf(output, s,a,b,c,d,e,f,g);}
  156.  
  157. static void
  158. #ifdef __USE_PROTOS
  159. warn_about_using_gk_option(void)
  160. #else
  161. warn_about_using_gk_option()
  162. #endif
  163. {
  164.     static int warned_already=0;
  165.  
  166.     if ( !DemandLookahead || warned_already ) return;
  167.     warned_already = 1;
  168.     warnNoFL("-gk option could cause trouble for <<...>>? predicates");
  169. }
  170.  
  171. void
  172. #ifdef __USE_PROTOS
  173. freeBlkFsets( Junction *q )
  174. #else
  175. freeBlkFsets( q )
  176. Junction *q;
  177. #endif
  178. {
  179.     int i;
  180.     Junction *alt;
  181.     require(q!=NULL, "freeBlkFsets: invalid node");
  182.  
  183.     for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
  184.     {
  185.         for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]);
  186.     }
  187. }
  188.  
  189. /*
  190.  * Generate a local variable allocation for each token references
  191.  * in this block.
  192.  */
  193. static void
  194. #ifdef __USE_PROTOS
  195. genTokenPointers( Junction *q )
  196. #else
  197. genTokenPointers( q )
  198. Junction *q;
  199. #endif
  200. {
  201.     /* Rule refs are counted and can be referenced, but their
  202.      * value is not set to anything useful ever.
  203.      *
  204.      * The ptrs are to be named _tij where i is the current level
  205.      * and j is the element number within an alternative.
  206.      */
  207.     int first=1, t;
  208.     set a;
  209.     tokensRefdInBlock = q->tokrefs;
  210.  
  211.     if ( set_deg(q->tokrefs) == 0 ) return;
  212.     a = set_dup(q->tokrefs);
  213.     gen("ANTLRToken ");
  214.     for (; !set_nil(a); set_rm(t, a))
  215.     {
  216.         t = set_int(a);
  217.         if ( first ) first = 0;
  218.         else _gen(",");
  219.         if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t);
  220.         _gen2("*_t%d%d", BlkLevel, t);
  221.         if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);}
  222.         else _gen("=NULL");
  223.     }
  224.     _gen(";\n");
  225.     set_free(a);
  226. }
  227.  
  228. static int
  229. #ifdef __USE_PROTOS
  230. hasDefaultException(ExceptionGroup *eg)
  231. #else
  232. hasDefaultException(eg)
  233. ExceptionGroup *eg;
  234. #endif
  235. {
  236.     ListNode *q;
  237.  
  238.     for (q = eg->handlers->next; q!=NULL; q=q->next)
  239.     {
  240.         ExceptionHandler *eh = (ExceptionHandler *)q->elem;
  241.         if ( strcmp("default", eh->signalname)==0 ) {
  242.             return 1;
  243.         }
  244.     }
  245.     return 0;
  246. }
  247.  
  248. static void
  249. #ifdef __USE_PROTOS
  250. dumpException(ExceptionGroup *eg, int no_default_case)
  251. #else
  252. dumpException(eg, no_default_case)
  253. ExceptionGroup *eg;
  254. int no_default_case;
  255. #endif
  256. {
  257.     gen1("switch ( _signal ) {\n", eg->label==NULL?"":eg->label);
  258.     {    
  259.         ListNode *q;
  260.         for (q = eg->handlers->next; q!=NULL; q=q->next)
  261.         {
  262.             ExceptionHandler *eh = (ExceptionHandler *)q->elem;
  263.             if ( strcmp("default", eh->signalname)==0 ) {
  264.                 gen("default :\n");
  265.                 tabs++;
  266.                 dumpAction(eh->action, output, tabs, -1, 1, 1);
  267.                 gen("_signal = NoSignal;\n");
  268.                 tabs--;
  269.                 gen("}\n");
  270.                 return;
  271.             }
  272.             gen1("case %s :\n", eh->signalname);
  273.             tabs++;
  274.             if ( eh->action != NULL )
  275.             {
  276.                 dumpAction(eh->action, output, tabs, -1, 1, 1);
  277.                 gen("_signal = NoSignal;\n");
  278.                 gen("break;\n");
  279.             }
  280.             tabs--;
  281.         }
  282.     }
  283.     if ( no_default_case ) return;
  284.  
  285.     gen("default :\n");
  286.     tabs++;
  287. /*    gen("*_retsignal = _signal;\n");*/
  288.     gen("goto _handler;\n");
  289.     tabs--;
  290.     gen("}\n");
  291. }
  292.  
  293. static void
  294. #ifdef __USE_PROTOS
  295. dumpExceptions(ListNode *list)
  296. #else
  297. dumpExceptions(list)
  298. ListNode *list;
  299. #endif
  300. {
  301.     ListNode *p;
  302.  
  303.     for (p = list->next; p!=NULL; p=p->next)
  304.     {
  305.         ExceptionGroup *eg = (ExceptionGroup *) p->elem;
  306.         _gen2("%s%s_handler:\n",
  307.               eg->label==NULL?"":eg->label,
  308.               eg->altID==NULL?"":eg->altID);
  309.         if ( eg->altID!=NULL ) dumpException(eg, 0);
  310.         else {
  311.             /* This must be the rule exception handler */
  312.             dumpException(eg, 1);
  313.             if ( !hasDefaultException(eg) )
  314.             {
  315.                 gen("default :\n");
  316.                 tabs++;
  317.                 gen("zzdflthandlers(_signal,_retsignal);\n");
  318.                 tabs--;
  319.                 gen("}\n");
  320.             }
  321.         }
  322.     }
  323. }
  324.  
  325. /* For each element label that is found in a rule, generate a unique
  326.  * Attribute (and AST pointer if GenAST) variable.
  327.  */
  328. void
  329. #ifdef __USE_PROTOS
  330. genElementLabels(ListNode *list)
  331. #else
  332. genElementLabels(list)
  333. ListNode *list;
  334. #endif
  335. {
  336.     int first=1;
  337.     ListNode *p;
  338.  
  339.     if ( GenCC ) {gen("ANTLRToken");}
  340.     else {gen("Attrib");}
  341.     for (p = list->next; p!=NULL; p=p->next)
  342.     {
  343.         char *ep = (char *)p->elem;
  344.         if ( first ) first = 0;
  345.         else _gen(",");
  346.         if ( GenCC ) {_gen1(" *%s=NULL",ep);}
  347.         else {_gen1(" %s",ep);}
  348.     }
  349.     _gen(";\n");
  350.  
  351.     if ( !GenAST ) return;
  352.  
  353.     first = 1;
  354.     gen("AST");
  355.     for (p = list->next; p!=NULL; p=p->next)
  356.     {
  357.         char *ep = (char *)p->elem;
  358.         if ( first ) first = 0;
  359.         else _gen(",");
  360.         _gen1(" *%s_ast=NULL",ep);
  361.     }
  362.     _gen(";\n");
  363. }
  364.  
  365. /*
  366.  * Generate a local variable allocation for each token or rule reference
  367.  * in this block.
  368.  */
  369. static void
  370. #ifdef __USE_PROTOS
  371. genASTPointers( Junction *q )
  372. #else
  373. genASTPointers( q )
  374. Junction *q;
  375. #endif
  376. {
  377.     int first=1, t;
  378.     set a;
  379.  
  380.     a = set_or(q->tokrefs, q->rulerefs);
  381.     if ( set_deg(a) > 0 )
  382.     {
  383.         gen("AST ");
  384.         for (; !set_nil(a); set_rm(t, a))
  385.         {
  386.             t = set_int(a);
  387.             if ( first ) first = 0;
  388.             else _gen(",");
  389.             _gen2("*_ast%d%d=NULL", BlkLevel, t);
  390.         }
  391.         set_free(a);
  392.     }
  393.     _gen(";\n");
  394. }
  395.  
  396. static void
  397. #ifdef __USE_PROTOS
  398. BLOCK_Head( void )
  399. #else
  400. BLOCK_Head( )
  401. #endif
  402. {
  403.     gen("{\n");
  404.     tabs++;
  405.     if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
  406. }
  407.  
  408. static void
  409. #ifdef __USE_PROTOS
  410. BLOCK_Tail( void )
  411. #else
  412. BLOCK_Tail( )
  413. #endif
  414. {
  415.     if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
  416.     if ( !GenCC ) gen("}\n");
  417.     tabs--;
  418.     gen("}\n");
  419. }
  420.  
  421. static void
  422. #ifdef __USE_PROTOS
  423. BLOCK_Preamble( Junction *q )
  424. #else
  425. BLOCK_Preamble( q )
  426. Junction *q;
  427. #endif
  428. {
  429.     ActionNode *a;
  430.     Junction *begin;
  431.  
  432.     BLOCK_Head();
  433.     if ( GenCC ) genTokenPointers(q);
  434.     if ( GenCC&&GenAST ) genASTPointers(q);
  435.     if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n");
  436.     if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm)
  437.     else if ( !GenCC ) gen("zzMake0;\n");
  438.     if ( !GenCC ) gen("{\n");
  439.     if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1);
  440.     else begin = q;
  441.     if ( has_guess_block_as_first_item(begin) )
  442.     {
  443.         gen("zzGUESS_BLOCK\n");
  444.     }
  445.     if ( q->jtype == aLoopBegin )
  446.         a = findImmedAction( ((Junction *)q->p1)->p1 );    /* look at aLoopBlk */
  447.     else
  448.         a = findImmedAction( q->p1 );
  449.     if ( a!=NULL && !a->is_predicate ) {
  450.         dumpAction(a->action, output, tabs, a->file, a->line, 1);
  451.         a->done = 1;    /* remove action. We have already handled it */
  452.     }
  453. }
  454.  
  455. /* If predicates are allowed in parsing expressions:
  456.  *
  457.  * (    production 1
  458.  * |    production 2
  459.  * ...
  460.  * |    production n
  461.  * )
  462.  *
  463.  * where production 1 yields visible predicates: <<pred>>? <<pred2>>?
  464.  *
  465.  * generates (if -prc on):
  466.  *
  467.  * if ( (production 1 prediction) &&
  468.  *        (context_of_pred && pred) &&
  469.  *        (context_of_pred2 && pred2) ) {
  470.  *         ...
  471.  * }
  472.  * else if ( production 2 prediction ) {
  473.  *         ...
  474.  * }
  475.  * ...
  476.  *
  477.  *        p1
  478.  *        |
  479.  *        p2--p3
  480.  *
  481.  * results in
  482.  *
  483.  * if ( (production 1 prediction) &&
  484.  *        (context_of_p1 && p1) &&
  485.  *        ((context_of_p2 && p2)||
  486.  *        (context_of_p3 && p3)) &&
  487.  *        ) {
  488.  *         ...
  489.  * }
  490.  *
  491.  * If no context, then just test expression.
  492.  */
  493. void
  494. #ifdef __USE_PROTOS
  495. genPredTree( Predicate *p, Junction *j )
  496. #else
  497. genPredTree( p, j )
  498. Predicate *p;
  499. Junction *j;
  500. #endif
  501. {
  502.     int context_was_present = 0;
  503.  
  504.     _gen("(");
  505.     for (; p!=NULL; p=p->right)
  506.     {
  507.         if ( HoistPredicateContext )
  508.         {
  509.             context_was_present = 0;
  510.             if ( LL_k>1 && p->tcontext!=NULL )
  511.             {
  512.                 context_was_present = 1;
  513.                 _gen("((");
  514.                 genExprTree(p->tcontext, 1);
  515.                 _gen(") ? ");
  516.             }
  517.             else if ( LL_k==1 && set_deg(p->scontext[1])>0 )
  518.             {
  519.                 context_was_present = 1;
  520.                 _gen("((");
  521.                 genExprSets(&(p->scontext[0]), CLL_k);
  522.                 _gen(") ? ");
  523.             }
  524.         }
  525.  
  526.         if ( FoundException ) {_gen("(_sva=(");}
  527.         else {_gen("(");}
  528.         dumpAction(p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0);
  529.         if ( FoundException ) {_gen("))");}
  530.         else {_gen(")");}
  531.  
  532.         if ( HoistPredicateContext && context_was_present ) _gen(" : 1)");
  533.  
  534.         if ( p->down!=NULL )
  535.         {
  536.             _gen("&&");
  537.             genPredTree(p->down, j);
  538.         }
  539.  
  540.         if ( p->right!=NULL ) _gen("||");
  541.     }
  542.     _gen(")");
  543. }
  544.  
  545. static void
  546. #ifdef __USE_PROTOS
  547. genExprTree( Tree *t, int k )
  548. #else
  549. genExprTree( t, k )
  550. Tree *t;
  551. int k;
  552. #endif
  553. {
  554.     require(t!=NULL, "genExprTree: NULL tree");
  555.     
  556.     if ( t->token == ALT )
  557.     {
  558.         _gen("("); genExprTree(t->down, k); _gen(")");
  559.         if ( t->right!=NULL )
  560.         {
  561.             _gen("||");
  562.             on1line++;
  563.             if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  564.             _gen("("); genExprTree(t->right, k); _gen(")");
  565.         }
  566.         return;
  567.     }
  568.     if ( t->down!=NULL ) _gen("(");
  569.     _gen1("LA(%d)==",k);
  570.     if ( TokenString(t->token) == NULL ) _gen1("%d", t->token)
  571.     else _gen1("%s", TokenString(t->token));
  572.     if ( t->down!=NULL )
  573.     {
  574.         _gen("&&");
  575.         on1line++;
  576.         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  577.         _gen("("); genExprTree(t->down, k+1); _gen(")");
  578.     }
  579.     if ( t->down!=NULL ) _gen(")");
  580.     if ( t->right!=NULL )
  581.     {
  582.         _gen("||");
  583.         on1line++;
  584.         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  585.         _gen("("); genExprTree(t->right, k); _gen(")");
  586.     }
  587. }
  588.  
  589. /*
  590.  * Generate LL(k) type expressions of the form:
  591.  *
  592.  *         (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) &&
  593.  *         (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) &&
  594.  *            .....
  595.  *         (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn)
  596.  *
  597.  * If GenExprSets generate:
  598.  *
  599.  *        (setwdi[LA(1)]&(1<<j)) && (setwdi[LA(2)]&(1<<j)) ...
  600.  *
  601.  * where n is set_deg(expr) and Ti is some random token and k is the last nonempty
  602.  * set in fset <=CLL_k.
  603.  * k=1..CLL_k where CLL_k >= 1.
  604.  *
  605.  * This routine is visible only to this file and cannot answer a TRANS message.
  606.  *
  607.  */
  608. static int
  609. #ifdef __USE_PROTOS
  610. genExpr( Junction *j )
  611. #else
  612. genExpr( j )
  613. Junction *j;
  614. #endif
  615. {
  616.     int max_k;
  617.  
  618.     /* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead
  619.      * from CLL_k..LL_k
  620.      */
  621.     {
  622.         int limit;
  623.         if ( j->ftree!=NULL ) limit = LL_k;
  624.         else limit = CLL_k;
  625.         max_k = genExprSets(j->fset, limit);
  626.     }
  627.  
  628.     /* Do tests for real tuples from other productions that conflict with
  629.      * artificial tuples generated by compression (using sets of tokens
  630.      * rather than k-trees).
  631.      */
  632.     if ( j->ftree != NULL )
  633.     {
  634.         _gen(" && !("); genExprTree(j->ftree, 1); _gen(")");
  635.     }
  636.  
  637.     if ( ParseWithPredicates && j->predicate!=NULL )
  638.     {
  639.         Predicate *p = j->predicate;
  640.         warn_about_using_gk_option();
  641.         _gen("&&");
  642.         genPredTree(p, j);
  643.     }
  644.  
  645.     return max_k;
  646. }
  647.  
  648. static int
  649. #ifdef __USE_PROTOS
  650. genExprSets( set *fset, int limit )
  651. #else
  652. genExprSets( fset, limit )
  653. set *fset;
  654. int limit;
  655. #endif
  656. {
  657.     int k = 1;
  658.     int max_k = 0;
  659.     unsigned *e, *g, firstTime=1;
  660.  
  661.     if ( GenExprSets )
  662.     {
  663.         while ( !set_nil(fset[k]) && k<=limit )
  664.         {
  665.             if ( set_deg(fset[k])==1 )    /* too simple for a set? */
  666.             {
  667.                 int e;
  668.                 _gen1("(LA(%d)==",k);
  669.                 e = set_int(fset[k]);
  670.                 if ( TokenString(e) == NULL ) _gen1("%d)", e)
  671.                 else _gen1("%s)", TokenString(e));
  672.             }
  673.             else
  674.             {
  675.                 NewSet();
  676.                 FillSet( fset[k] );
  677.                 _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<<setnum);
  678.             }
  679.             if ( k>max_k ) max_k = k;
  680.             if ( k == CLL_k ) break;
  681.             k++;
  682.             if ( !set_nil(fset[k]) && k<=limit ) _gen(" && ");
  683.             on1line++;
  684.             if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  685.         }
  686.         return max_k;
  687.     }
  688.  
  689.     while ( !set_nil(fset[k]) && k<=limit )
  690.     {
  691.         if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set");
  692.         for (; *e!=nil; e++)
  693.         {
  694.             if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; }
  695.             on1line++;
  696.             if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  697.             _gen1("LA(%d)==",k);
  698.             if ( TokenString(*e) == NULL ) _gen1("%d", *e)
  699.             else _gen1("%s", TokenString(*e));
  700.         }
  701.         free( (char *)g );
  702.         _gen(")");
  703.         if ( k>max_k ) max_k = k;
  704.         if ( k == CLL_k ) break;
  705.         k++;
  706.         if ( !set_nil(fset[k]) && k<=limit ) { firstTime=1; _gen(" && "); }
  707.         on1line++;
  708.         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  709.     }
  710.     return max_k;
  711. }
  712.  
  713. /*
  714.  * Generate code for any type of block.  If the last alternative in the block is
  715.  * empty (not even an action) don't bother doing it.  This permits us to handle
  716.  * optional and loop blocks as well.
  717.  *
  718.  * Only do this block, return after completing the block.
  719.  * This routine is visible only to this file and cannot answer a TRANS message.
  720.  */
  721. static set
  722. #ifdef __USE_PROTOS
  723. genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly )
  724. #else
  725. genBlk( q, jtype, max_k, need_right_curly )
  726. Junction *q;
  727. int jtype;
  728. int *max_k;
  729. int *need_right_curly;
  730. #endif
  731. {
  732.     set f;
  733.     Junction *alt;
  734.     int a_guess_in_block = 0;
  735.     require(q!=NULL,                "genBlk: invalid node");
  736.     require(q->ntype == nJunction,    "genBlk: not junction");
  737.  
  738.     *need_right_curly=0;
  739.     if ( q->p2 == NULL )    /* only one alternative?  Then don't need if */
  740.     {    
  741.         if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
  742.         {
  743.             warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line);
  744.             gen("zzGUESS\n");    /* guess anyway to make output code consistent */
  745.             gen("if ( !zzrv )\n");
  746.         }
  747.         TRANS(q->p1);
  748.         return empty;        /* no decision to be made-->no error set */
  749.     }
  750.  
  751.     f = First(q, 1, jtype, max_k);
  752.     for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
  753.     {
  754.         if ( alt->p2 == NULL )                    /* chk for empty alt */
  755.         {    
  756.             Node *p = alt->p1;
  757.             if ( p->ntype == nJunction )
  758.             {
  759.                 /* we have empty alt */
  760.                 if ( ((Junction *)p)->p1 == (Node *)q->end )
  761.                 {
  762.                     break;                        /* don't do this one, quit */
  763.                 }
  764.             }
  765.         }
  766.         if ( alt != q ) gen("else ")
  767.         else
  768.         {
  769.             if ( DemandLookahead )
  770.                 if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);}
  771.                 else gen1("look(%d);\n", *max_k);
  772.         }
  773.         if ( alt!=q )
  774.         {
  775.             _gen("{\n");
  776.             tabs++;
  777.             (*need_right_curly)++;
  778.             /* code to restore state if a prev alt didn't follow guess */
  779.             if ( a_guess_in_block )
  780.                    if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_DONE;\n");}
  781.                 else gen("if ( guessing ) zzGUESS_DONE;\n");
  782.         }
  783.         if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL )
  784.         {
  785.             a_guess_in_block = 1;
  786.             gen("zzGUESS\n");
  787.         }
  788.         gen("if ( ");
  789.         if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && ");
  790.         genExpr(alt);
  791.         _gen(" ) ");
  792.         _gen("{\n");
  793.         tabs++;
  794.         TRANS(alt->p1);
  795.         --tabs;
  796.         gen("}\n");
  797.     }
  798.     return f;
  799. }
  800.  
  801. static int
  802. #ifdef __USE_PROTOS
  803. has_guess_block_as_first_item( Junction *q )
  804. #else
  805. has_guess_block_as_first_item( q )
  806. Junction *q;
  807. #endif
  808. {
  809.     Junction *alt;
  810.  
  811.     for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
  812.     {
  813.         if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1;
  814.     }
  815.     return 0;
  816. }
  817.  
  818. /* return NULL if 1st item of alt is (...)? block; else return ptr  
  819. to aSubBlk node
  820.  * of (...)?;  This function ignores actions and predicates.
  821.  */
  822. Junction *
  823. #ifdef __USE_PROTOS
  824. first_item_is_guess_block( Junction *q )
  825. #else
  826. first_item_is_guess_block( q )
  827. Junction *q;
  828. #endif
  829. {
  830.     while ( q!=NULL && ((q->ntype==nJunction && q->jtype==Generic) || q->ntype==nAction) )
  831.     {
  832.         if ( q->ntype==nJunction ) q = (Junction *)q->p1;
  833.         else q = (Junction *) ((ActionNode *)q)->next;
  834.     }
  835.  
  836.     if ( q==NULL ) return NULL;
  837.     if ( q->ntype!=nJunction ) return NULL;
  838.     if ( q->jtype!=aSubBlk ) return NULL;
  839.     if ( !q->guess ) return NULL;
  840.     return q;
  841. }
  842.  
  843. /* Generate an action.  Don't if action is NULL which means that it was already
  844.  * handled as an init action.
  845.  */
  846. void
  847. #ifdef __USE_PROTOS
  848. genAction( ActionNode *p )
  849. #else
  850. genAction( p )
  851. ActionNode *p;
  852. #endif
  853. {
  854.     require(p!=NULL,            "genAction: invalid node and/or rule");
  855.     require(p->ntype==nAction,    "genAction: not action");
  856.     
  857.     if ( !p->done )
  858.     {
  859.         if ( p->is_predicate )
  860.         {
  861.             gen("if (!(");
  862.             /* make sure that '#line n' is on front of line */
  863.             if ( GenLineInfo && p->file != -1 ) _gen("\n");
  864.             dumpAction(p->action, output, 0, p->file, p->line, 0);
  865.             if ( p->pred_fail != NULL )
  866.             {
  867.                 _gen("))\n");
  868. /*                if ( FoundGuessBlk ) gen("zzNON_GUESS_MODE {\n");*/
  869.                 tabs++;
  870.                 gen1("%s;\n", p->pred_fail);
  871.                 tabs--;
  872. /*                if ( FoundGuessBlk ) gen("}\n");*/
  873.             }
  874.             else _gen1(")) {zzfailed_pred((ANTLRChar *)\"%s\");}\n",p->action);
  875.         }
  876.         else
  877.         {
  878.             if ( FoundGuessBlk )
  879.                 if ( GenCC ) {gen("if ( !guessing ) {\n");}
  880.                 else gen("zzNON_GUESS_MODE {\n");
  881.             dumpAction(p->action, output, tabs, p->file, p->line, 1);
  882.             if ( FoundGuessBlk ) gen("}\n");
  883.         }
  884.     }
  885.     TRANS(p->next)
  886. }
  887.  
  888. /*
  889.  *        if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in
  890.  *        else pass addr of temp root ptr (&_ast) (don't zzlink it in).
  891.  *
  892.  *        if ! modifies rule-ref, then never link it in and never pass zzSTR.
  893.  *        Always pass address of temp root ptr.
  894.  */
  895. void
  896. #ifdef __USE_PROTOS
  897. genRuleRef( RuleRefNode *p )
  898. #else
  899. genRuleRef( p )
  900. RuleRefNode *p;
  901. #endif
  902. {
  903.     Junction *q;
  904.     char *handler_id = "";
  905.     RuleEntry *r, *r2;
  906.     char *parm = "", *exsig = "";
  907.     require(p!=NULL,            "genRuleRef: invalid node and/or rule");
  908.     require(p->ntype==nRuleRef, "genRuleRef: not rule reference");
  909.     
  910.     if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
  911.         handler_id = p->altstart->exception_label;
  912.  
  913.     r = (RuleEntry *) hash_get(Rname, p->text);
  914.     if ( r == NULL )
  915.     {
  916.         warnFL( eMsg1("rule %s not defined",
  917.                       p->text), FileStr[p->file], p->line );
  918.         return;
  919.     }
  920.     r2 = (RuleEntry *) hash_get(Rname, p->rname);
  921.     if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
  922.  
  923.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, p->line, FileStr[p->file]);
  924.  
  925.     if ( GenCC && GenAST ) {
  926.         gen("_ast = NULL;\n");
  927.     }
  928.  
  929.     if ( FoundGuessBlk && p->assign!=NULL )
  930.         if ( GenCC ) {gen("if ( !guessing ) {\n");}
  931.         else gen("zzNON_GUESS_MODE {\n");
  932.  
  933.     if ( FoundException ) exsig = "&_signal";
  934.  
  935.     tab();
  936.     if ( GenAST )
  937.     {
  938.         if ( GenCC ) {
  939. /*            if ( r2->noAST || p->astnode==ASTexclude )
  940. */
  941.             {
  942. /*                _gen("_ast = NULL;\n");*/
  943.                 parm = "&_ast";
  944.             }
  945. /* we always want to set just a pointer now, then set correct  
  946. pointer after
  947.  
  948.             else {
  949.                 _gen("_astp =  
  950. (_tail==NULL)?(&_sibling):(&(_tail->_right));\n");
  951.                 parm = "_astp";
  952.             }
  953. */
  954.         }
  955.         else {
  956.             if ( r2->noAST || p->astnode==ASTexclude )
  957.             {
  958.                 _gen("_ast = NULL; ");
  959.                 parm = "&_ast";
  960.             }
  961.             else parm = "zzSTR";
  962.         }
  963.         if ( p->assign!=NULL )
  964.         {
  965.             if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
  966.             else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
  967.         }
  968.         if ( FoundException ) {
  969.             _gen5("%s%s(%s,&_signal%s%s); ",
  970.                   RulePrefix,
  971.                   p->text,
  972.                   parm,
  973.                   (p->parms!=NULL)?",":"",
  974.                   (p->parms!=NULL)?p->parms:"");
  975.             if ( p->ex_group!=NULL ) {
  976.                 _gen("\n");
  977.                 gen("if (_signal) {\n");
  978.                 tabs++;
  979.                 dumpException(p->ex_group, 0);
  980.                 tabs--;
  981.                 gen("}");
  982.             }
  983.             else {
  984.                 _gen1("if (_signal) goto %s_handler;", handler_id);
  985.             }
  986.         }
  987.         else {
  988.             _gen5("%s%s(%s%s%s);",
  989.                   RulePrefix,
  990.                   p->text,
  991.                   parm,
  992.                   (p->parms!=NULL)?",":"",
  993.                   (p->parms!=NULL)?p->parms:"");
  994.         }
  995.         if ( GenCC && (r2->noAST || p->astnode==ASTexclude) )
  996.         {
  997.             /* rule has a ! or element does */
  998.             /* still need to assign to #i so we can play with it */
  999.             _gen("\n");
  1000.             gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum);
  1001.         }
  1002.         else if ( !r2->noAST && p->astnode == ASTinclude )
  1003.         {
  1004.             /* rule doesn't have a ! and neither does element */
  1005.             if ( GenCC ) {
  1006.                 _gen("\n");
  1007.                 gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n");
  1008.                 gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum);
  1009.                 tab();
  1010.             }
  1011.             else _gen(" ");
  1012.             if ( GenCC ) {_gen("ASTBase::");} else _gen("zz");
  1013.             _gen("link(_root, &_sibling, &_tail);");
  1014.         }
  1015.     }
  1016.     else
  1017.     {
  1018.         if ( p->assign!=NULL )
  1019.         {
  1020.             if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
  1021.             else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
  1022.         }
  1023.         if ( FoundException ) {
  1024.             _gen4("%s%s(&_signal%s%s); ",
  1025.                   RulePrefix,
  1026.                   p->text,
  1027.                   (p->parms!=NULL)?",":"",
  1028.                   (p->parms!=NULL)?p->parms:"");
  1029.             if ( p->ex_group!=NULL ) {
  1030.                 _gen("\n");
  1031.                 gen("if (_signal) {\n");
  1032.                 tabs++;
  1033.                 dumpException(p->ex_group, 0);
  1034.                 tabs--;
  1035.                 gen("}");
  1036.             }
  1037.             else {
  1038.                 _gen1("if (_signal) goto %s_handler;", handler_id);
  1039.             }
  1040.         }
  1041.         else {
  1042.             _gen3("%s%s(%s);",
  1043.                   RulePrefix,
  1044.                   p->text,
  1045.                   (p->parms!=NULL)?p->parms:"");
  1046.         }
  1047.         if ( p->assign!=NULL ) _gen("\n");
  1048.     }
  1049.     q = RulePtr[r->rulenum];    /* find definition of ref'd rule */
  1050.     if ( p->assign!=NULL ) {
  1051.         if ( HasComma(p->assign) )
  1052.         {
  1053.             _gen("\n");
  1054.             dumpRetValAssign(p->assign, q->ret);
  1055.             _gen("}");
  1056.         }
  1057.     }
  1058.     _gen("\n");
  1059.  
  1060.     /* Handle element labels now */
  1061.     if ( p->el_label!=NULL )
  1062.     {
  1063.         if ( GenAST )
  1064.         {
  1065.             if ( GenCC ) {
  1066.                 gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
  1067.             }
  1068.             else {gen1("%s_ast = zzastCur;\n", p->el_label);}
  1069.         }
  1070.     }
  1071.  
  1072.     if ( FoundGuessBlk && p->assign!=NULL ) {
  1073.         /* in guessing mode, don't branch to handler upon error */
  1074.         gen("} else {\n");
  1075.         if ( FoundException ) {
  1076.             gen6("%s%s(%s%s&_signal%s%s);\n",
  1077.                  RulePrefix,
  1078.                  p->text,
  1079.                  parm,
  1080.                  (*parm!='\0')?",":"",
  1081.                  (p->parms!=NULL)?",":"",
  1082.                  (p->parms!=NULL)?p->parms:"");
  1083.         }
  1084.         else {
  1085.             gen5("%s%s(%s%s%s);\n",
  1086.                  RulePrefix,
  1087.                  p->text,
  1088.                  parm,
  1089.                  (p->parms!=NULL && *parm!='\0')?",":"",
  1090.                  (p->parms!=NULL)?p->parms:"");
  1091.         }
  1092.         gen("}\n");
  1093.     }
  1094.     TRANS(p->next)
  1095. }
  1096.  
  1097. /*
  1098.  * Generate code to match a token.
  1099.  *
  1100.  * Getting the next token is tricky.  We want to ensure that any action
  1101.  * following a token is executed before the next GetToken();
  1102.  */
  1103. void
  1104. #ifdef __USE_PROTOS
  1105. genToken( TokNode *p )
  1106. #else
  1107. genToken( p )
  1108. TokNode *p;
  1109. #endif
  1110. {
  1111.     TermEntry *tcsym;
  1112.     RuleEntry *r;
  1113.     char *handler_id = "";
  1114.     ActionNode *a;
  1115.     require(p!=NULL,            "genToken: invalid node and/or rule");
  1116.     require(p->ntype==nToken,    "genToken: not token");
  1117.     
  1118.     if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
  1119.         handler_id = p->altstart->exception_label;
  1120.  
  1121.     r = (RuleEntry *) hash_get(Rname, p->rname);
  1122.     if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
  1123.  
  1124.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, p->line, FileStr[p->file]);
  1125.  
  1126.     if ( !set_nil(p->tset) )
  1127.     {
  1128.         unsigned e;
  1129.         set b;
  1130.         b = set_dup(p->tset);
  1131. #ifdef DUM
  1132.         tcsym = (TermEntry *)hash_get(Tname, TokenString(p->token));
  1133.         require(tcsym!=NULL, "cannot find tokclass in sym tab");
  1134.         if ( tcsym->tclass->dumped ) e = tcsym->tclass->setnum;
  1135. #else
  1136.         if ( p->tclass->dumped ) e = p->tclass->setnum;
  1137. #endif
  1138.         else {
  1139.             e = DefErrSet(&b, 0, TokenString(p->token));
  1140.             p->tclass->dumped = 1;        /* indicate that a set has been created */
  1141. #ifdef DUM
  1142.             tcsym->tclass->setnum = e;
  1143. #else
  1144.             p->tclass->setnum = e;
  1145. #endif
  1146.         }
  1147.         if ( !FoundException )
  1148.             {gen1("zzsetmatch(%s_set);", TokenString(p->token));}
  1149.         else {
  1150.             if ( p->use_def_MT_handler )
  1151.                 gen3("zzsetmatch_wdfltsig(%s_set,(TokenType)%d,%s);",
  1152.                      TokenString(p->token),
  1153.                      p->token,
  1154.                      tokenFollowSet(p))
  1155.             else
  1156.                 gen2("zzsetmatch_wsig(%s_set, %s_handler);",
  1157.                      TokenString(p->token),
  1158.                      handler_id);
  1159.         }
  1160.         set_free(b);
  1161.     }
  1162.     else if ( TokenString(p->token)!=NULL )
  1163.     {
  1164.         if ( FoundException ) {
  1165.             if ( p->use_def_MT_handler )
  1166.                 gen2("zzmatch_wdfltsig(%s,%s);",TokenString(p->token),tokenFollowSet(p))
  1167.             else
  1168.                 gen2("zzmatch_wsig(%s, %s_handler);",
  1169.                      TokenString(p->token),
  1170.                      handler_id);
  1171.         }
  1172.         else gen1("zzmatch(%s);", TokenString(p->token));
  1173.     }
  1174.     else {
  1175.         if ( FoundException ) {
  1176.             if ( p->use_def_MT_handler )
  1177.                 gen2("zzmatch_wdfltsig((TokenType)%d,%s);",
  1178.                      p->token,tokenFollowSet(p))
  1179.             else
  1180.                 gen2("zzmatch_wsig(%d,%s_handler);",p->token,handler_id);
  1181.         }
  1182.         else {gen1("zzmatch(%d);", p->token);}
  1183.     }
  1184.  
  1185.     a = findImmedAction( p->next );
  1186.     /* generate the token copies */
  1187.     if ( GenCC && p->elnum>0 )
  1188.     {
  1189.         /* If building trees in C++, always gen the LT() assigns */
  1190.         if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {
  1191.             if ( !DontCopyTokens )
  1192.                 {_gen2(" *_t%d%d = *((ANTLRToken *)LT(1));", BlkLevel-1, p->elnum);}
  1193.             else
  1194.                 _gen2(" _t%d%d = (ANTLRToken *)LT(1);", BlkLevel-1, p->elnum);
  1195.         }
  1196.         if ( LL_k>1 )
  1197.             if ( !DemandLookahead ) _gen(" labase++;");
  1198.         _gen("\n");
  1199.         tab();
  1200.     }
  1201.     if ( GenAST )
  1202.     {
  1203.         if ( FoundGuessBlk && !(p->astnode == ASTexclude || r->noAST) )
  1204.         {
  1205.             if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();}
  1206.             else {_gen("zzNON_GUESS_MODE {\n"); tab();}
  1207.         }
  1208.         if ( !r->noAST )
  1209.         {
  1210.             if ( GenCC && !(p->astnode == ASTexclude || r->noAST) ) {
  1211.                 _gen("\n");
  1212.                 gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
  1213.                 tab();
  1214.             }
  1215.             if ( GenCC && !(p->astnode == ASTexclude || r->noAST) )
  1216.                 {_gen2("_ast%d%d->", BlkLevel-1, p->elnum);}
  1217.             else _gen(" ");
  1218.             if ( p->astnode==ASTchild ) {
  1219.                 if ( !GenCC ) _gen("zz");
  1220.                 _gen("subchild(_root, &_sibling, &_tail);");
  1221.             }
  1222.             else if ( p->astnode==ASTroot ) {
  1223.                 if ( !GenCC ) _gen("zz");
  1224.                 _gen("subroot(_root, &_sibling, &_tail);");
  1225.             }
  1226.             if ( GenCC && !(p->astnode == ASTexclude || r->noAST) ) {
  1227.                 _gen("\n");
  1228.                 tab();
  1229.             }
  1230.         }
  1231.         else if ( !GenCC ) _gen(" zzastDPush;");
  1232.         if ( FoundGuessBlk && !(p->astnode == ASTexclude || r->noAST) )
  1233.             {_gen("}\n"); tab();}
  1234.     }
  1235.  
  1236.     /* Handle element labels now */
  1237.     if ( p->el_label!=NULL )
  1238.     {
  1239.         _gen("\n");
  1240.         if ( FoundGuessBlk )
  1241.         {
  1242.             if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
  1243.             else {gen("zzNON_GUESS_MODE {\n"); tab();}
  1244.         }
  1245.         /* Do Attrib / Token ptr */
  1246.         if ( GenCC ) {
  1247.             if ( set_el(p->elnum, tokensRefdInBlock) || GenAST )
  1248.                 {gen3("%s = _t%d%d;\n", p->el_label, BlkLevel-1, p->elnum);}
  1249.             else
  1250.                 {gen1("%s = (ANTLRToken *)LT(1);\n", p->el_label);}
  1251.         }
  1252.         else {gen1("%s = zzaCur;\n", p->el_label);}
  1253.         /* Do AST ptr */
  1254.         if ( GenAST && !(p->astnode == ASTexclude || r->noAST) )
  1255.         {
  1256.             if ( GenCC ) {
  1257.                 gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
  1258.             }
  1259.             else {gen1("%s_ast = zzastCur;\n", p->el_label);}
  1260.         }
  1261.  
  1262.         if ( FoundGuessBlk ) {_gen("}\n"); tab();}
  1263.     }
  1264.  
  1265.     /* Handle any actions immediately following action */
  1266.     if ( a != NULL )
  1267.     {
  1268.         /* delay next token fetch until after action */
  1269.         _gen("\n");
  1270.         if ( a->is_predicate )
  1271.         {
  1272.             gen("if (!(");
  1273.             dumpAction(a->action, output, 0, a->file, a->line, 0);
  1274.             if ( a->pred_fail != NULL )
  1275.             {
  1276.                 _gen("))\n");
  1277. /*                if ( FoundGuessBlk )  
  1278. gen("zzNON_GUESS_MODE {\n");*/
  1279.                 tabs++;
  1280.                 gen1("%s;\n", a->pred_fail);
  1281.                 tabs--;
  1282. /*                if ( FoundGuessBlk ) gen("}\n");*/
  1283.             }
  1284.             else _gen1(")) {zzfailed_pred((ANTLRChar *)\"%s\");}\n",a->action);
  1285.         }
  1286.         else
  1287.         {
  1288.             if ( FoundGuessBlk )
  1289.                 if ( GenCC ) {gen("if ( !guessing ) {\n");}
  1290.                 else gen("zzNON_GUESS_MODE {\n");
  1291.             dumpAction(a->action, output, tabs, a->file, a->line, 1);
  1292.             if ( FoundGuessBlk ) gen("}\n");
  1293.         }
  1294.         a->done = 1;
  1295.         if ( !DemandLookahead ) {
  1296.             if ( GenCC ) {
  1297.                 if ( FoundException && p->use_def_MT_handler ) gen("if (!_signal)");
  1298.                 _gen(" consume();")
  1299.                 if ( FoundException && p->use_def_MT_handler )
  1300.                     _gen(" _signal=NoSignal;");
  1301.                 _gen("\n");
  1302.             }
  1303.             else {
  1304.                 if ( FoundException && p->use_def_MT_handler ) _gen("if (!_signal)");
  1305.                     _gen(" zzCONSUME;\n");
  1306.                 if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
  1307.                 _gen("\n");
  1308.             }
  1309.         }
  1310.         else gen("\n");
  1311.         TRANS( a->next );
  1312.     }
  1313.     else
  1314.     {
  1315.         if ( !DemandLookahead ) {
  1316.             if ( GenCC ) {
  1317.                 if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
  1318.                 _gen(" consume();")
  1319.                 if (FoundException&&p->use_def_MT_handler) _gen(" _signal=NoSignal;");
  1320.                 _gen("\n");
  1321.             }
  1322.             else {
  1323.                 if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
  1324.                 _gen(" zzCONSUME;");
  1325.                 if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
  1326.                 _gen("\n");
  1327.             }
  1328.         }
  1329.         else _gen("\n");
  1330.         TRANS(p->next);
  1331.     }
  1332. }
  1333.  
  1334. void
  1335. #ifdef __USE_PROTOS
  1336. genOptBlk( Junction *q )
  1337. #else
  1338. genOptBlk( q )
  1339. Junction *q;
  1340. #endif
  1341. {
  1342.     int max_k;
  1343.     set f;
  1344.     int need_right_curly;
  1345.     require(q!=NULL,                "genOptBlk: invalid node and/or rule");
  1346.     require(q->ntype == nJunction,    "genOptBlk: not junction");
  1347.     require(q->jtype == aOptBlk,    "genOptBlk: not optional block");
  1348.  
  1349.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1350.     BLOCK_Preamble(q);
  1351.     BlkLevel++;
  1352.     f = genBlk(q, aOptBlk, &max_k, &need_right_curly);
  1353.     set_free(f);
  1354.     freeBlkFsets(q);
  1355.     BlkLevel--;
  1356.     if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
  1357.     {
  1358.         if ( !GenCC ) {gen("else if ( zzguessing ) zzGUESS_DONE;\n");}
  1359.         else gen("else if ( guessing ) zzGUESS_DONE;\n");
  1360.     }
  1361.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1362.     BLOCK_Tail();
  1363.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1364. }
  1365.  
  1366. /*
  1367.  * Generate code for a loop blk of form:
  1368.  *
  1369.  *                 |---|
  1370.  *                 v   |
  1371.  *               --o-G-o-->o--
  1372.  */
  1373. void
  1374. #ifdef __USE_PROTOS
  1375. genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k )
  1376. #else
  1377. genLoopBlk( begin, q, start, max_k )
  1378. Junction *begin;
  1379. Junction *q;
  1380. Junction *start;    /* where to start generating code from */
  1381. int max_k;
  1382. #endif
  1383. {
  1384.     set f;
  1385.     int need_right_curly;
  1386.     set savetkref;
  1387.     savetkref = tokensRefdInBlock;
  1388.     require(q->ntype == nJunction,    "genLoopBlk: not junction");
  1389.     require(q->jtype == aLoopBlk,    "genLoopBlk: not loop block");
  1390.  
  1391.     if ( q->visited ) return;
  1392.     q->visited = TRUE;
  1393.     if ( q->p2 == NULL )    /* only one alternative? */
  1394.     {
  1395.         if ( DemandLookahead )
  1396.             if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1397.             else gen1("look(%d);\n", max_k);
  1398.         gen("while ( ");
  1399.         if ( begin!=NULL ) genExpr(begin);
  1400.         else genExpr(q);
  1401.         /* if no predicates have been hoisted for this single alt (..)*
  1402.          * do so now
  1403.          */
  1404.         if ( ParseWithPredicates && begin->predicate==NULL )
  1405.         {
  1406.             Predicate *a = find_predicates((Node *)q->p1);
  1407.             if ( a!=NULL )
  1408.             {
  1409.                 _gen("&&");
  1410.                 genPredTree(a, q);
  1411.             }
  1412.         }
  1413.         _gen(" ) {\n");
  1414.         tabs++;
  1415.         TRANS(q->p1);
  1416.         if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
  1417.         if ( DemandLookahead )
  1418.             if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1419.             else gen1("look(%d);\n", max_k);
  1420.         --tabs;
  1421.         gen("}\n");
  1422.         freeBlkFsets(q);
  1423.         q->visited = FALSE;
  1424.         tokensRefdInBlock = savetkref;
  1425.         return;
  1426.     }
  1427.     gen("while ( 1 ) {\n");
  1428.     tabs++;
  1429.     if ( begin!=NULL )
  1430.     {
  1431.         if ( DemandLookahead )
  1432.         {
  1433.             if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1434.             else gen1("look(%d);\n", max_k);
  1435.         }
  1436.         /* The bypass arc of the (...)* predicts what to do when you fail, but
  1437.          * ONLY after having tested the loop start expression.  To avoid this,
  1438.          * we simply break out of the (...)* loop when we find something that
  1439.          * is not in the prediction of the loop (all alts thereof).
  1440.          */
  1441.         gen("if ( !(");
  1442.  
  1443. /*    TJP says: It used to use the prediction expression for the bypass arc
  1444.      of the (...)*.  HOWEVER, if a non LL^1(k) decision was found, this
  1445.     thing would miss the ftree stored in the aLoopBegin node and generate
  1446.     an LL^1(k) decision anyway.
  1447.  
  1448.         genExpr((Junction *)begin->p2);
  1449.  */
  1450.  
  1451.         genExpr((Junction *)begin);
  1452.         _gen(")) break;\n");
  1453.     }
  1454.     f = genBlk(q, aLoopBlk, &max_k, &need_right_curly);
  1455.     set_free(f);
  1456.     freeBlkFsets(q);
  1457.  
  1458.     /* generate code for terminating loop (this is optional branch) */
  1459.     if ( begin==NULL ) gen("else break;\n"); /* code for exiting loop "for sure" */
  1460.  
  1461.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1462.     if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
  1463.     --tabs;
  1464.     gen("}\n");
  1465.     q->visited = FALSE;
  1466.     tokensRefdInBlock = savetkref;
  1467. }
  1468.  
  1469. /*
  1470.  * Generate code for a loop blk of form:
  1471.  *
  1472.  *                          |---|
  1473.  *                         v   |
  1474.  *               --o-->o-->o-G-o-->o--
  1475.  *                   |           ^
  1476.  *                   v           |
  1477.  *                     o-----------o
  1478.  *
  1479.  * q->end points to the last node (far right) in the blk.  Note  
  1480. that q->end->jtype
  1481.  * must be 'EndBlk'.
  1482.  *
  1483.  * Generate code roughly of the following form:
  1484.  *
  1485.  *    do {
  1486.  *        ... code for alternatives ...
  1487.  *  } while ( First Set of aLoopBlk );
  1488.  *
  1489.  *    OR if > 1 alternative
  1490.  *
  1491.  *    do {
  1492.  *        ... code for alternatives ...
  1493.  *        else break;
  1494.  *  } while ( 1 );
  1495.  */
  1496. void
  1497. #ifdef __USE_PROTOS
  1498. genLoopBegin( Junction *q )
  1499. #else
  1500. genLoopBegin( q )
  1501. Junction *q;
  1502. #endif
  1503. {
  1504.     set f;
  1505.     int i;
  1506.     int max_k;
  1507.     set savetkref;
  1508.     savetkref = tokensRefdInBlock;
  1509.     require(q!=NULL,                "genLoopBegin: invalid node and/or rule");
  1510.     require(q->ntype == nJunction,    "genLoopBegin: not junction");
  1511.     require(q->jtype == aLoopBegin,    "genLoopBegin: not loop block");
  1512.     require(q->p2!=NULL,            "genLoopBegin: invalid Loop Graph");
  1513.  
  1514.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1515.  
  1516.     BLOCK_Preamble(q);
  1517.     BlkLevel++;
  1518.     f = First(q, 1, aLoopBegin, &max_k);
  1519.     /* If not simple LL(1), must specify to start at LoopBegin, not LoopBlk */
  1520.     if ( LL_k>1 && !set_nil(q->fset[2]) )
  1521.         genLoopBlk( q, (Junction *)q->p1, q, max_k );
  1522.     else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );
  1523.  
  1524.     for (i=1; i<=CLL_k; i++) set_free(q->fset[i]);
  1525.     for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]);
  1526.     --BlkLevel;
  1527.     BLOCK_Tail();
  1528.     set_free(f);
  1529.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1530.     tokensRefdInBlock = savetkref;
  1531. }
  1532.  
  1533. /*
  1534.  * Generate code for a loop blk of form:
  1535.  *
  1536.  *                      |---|
  1537.  *                     v   |
  1538.  *                   --o-G-o-->o--
  1539.  *
  1540.  * q->end points to the last node (far right) in the blk.
  1541.  * Note that q->end->jtype must be 'EndBlk'.
  1542.  *
  1543.  * Generate code roughly of the following form:
  1544.  *
  1545.  *    do {
  1546.  *        ... code for alternatives ...
  1547.  *  } while ( First Set of aPlusBlk );
  1548.  *
  1549.  *    OR if > 1 alternative
  1550.  *
  1551.  *    do {
  1552.  *        ... code for alternatives ...
  1553.  *        else if not 1st time through, break;
  1554.  *  } while ( 1 );
  1555.  */
  1556. void
  1557. #ifdef __USE_PROTOS
  1558. genPlusBlk( Junction *q )
  1559. #else
  1560. genPlusBlk( q )
  1561. Junction *q;
  1562. #endif
  1563. {
  1564.     int max_k;
  1565.     set f;
  1566.     int need_right_curly;
  1567.     set savetkref;
  1568.     savetkref = tokensRefdInBlock;
  1569.     require(q!=NULL,                "genPlusBlk: invalid node and/or rule");
  1570.     require(q->ntype == nJunction,    "genPlusBlk: not junction");
  1571.     require(q->jtype == aPlusBlk,    "genPlusBlk: not Plus block");
  1572.     require(q->p2 != NULL,            "genPlusBlk: not a valid Plus block");
  1573.  
  1574.     if ( q->visited ) return;
  1575.     q->visited = TRUE;
  1576.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1577.     BLOCK_Preamble(q);
  1578.     BlkLevel++;
  1579.     /* if the ignore flag is set on the 2nd alt and that alt is empty,
  1580.      * then it is the implied optional alternative that we added for (...)+
  1581.      * and, hence, only 1 alt.
  1582.      */
  1583.     if ( ((Junction *)q->p2)->p2 == NULL &&
  1584.          ((Junction *)q->p2)->ignore )            /* only one alternative? */
  1585.     {
  1586.         Predicate *a=NULL;
  1587.         /* if the only alt has a semantic predicate, hoist it; must test before
  1588.          * entering loop.
  1589.          */
  1590.         if ( ParseWithPredicates )
  1591.         {
  1592.             a = find_predicates((Node *)q);
  1593.             if ( a!=NULL ) {
  1594.                 gen("if (");
  1595.                 genPredTree(a, q);
  1596.                 _gen(") {\n");
  1597.             }
  1598.         }
  1599.         gen("do {\n");
  1600.         tabs++;
  1601.         TRANS(q->p1);
  1602.         if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
  1603.         f = First(q, 1, aPlusBlk, &max_k);
  1604.         if ( DemandLookahead )
  1605.             if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1606.             else gen1("look(%d);\n", max_k);
  1607.         --tabs;
  1608.         gen("} while ( ");
  1609.         if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm);
  1610.         genExpr(q);
  1611.         if ( ParseWithPredicates && a!=NULL )
  1612.         {
  1613.             _gen("&&");
  1614.             genPredTree(a, q);
  1615.         }
  1616.         _gen(" );\n");
  1617.         if ( ParseWithPredicates && a!=NULL ) gen("}\n");
  1618.         --BlkLevel;
  1619.         BLOCK_Tail();
  1620.         q->visited = FALSE;
  1621.         freeBlkFsets(q);
  1622.         set_free(f);
  1623.         if (q->end->p1 != NULL) TRANS(q->end->p1);
  1624.         tokensRefdInBlock = savetkref;
  1625.         return;
  1626.     }
  1627.     gen("do {\n");
  1628.     tabs++;
  1629.     f = genBlk(q, aPlusBlk, &max_k, &need_right_curly);
  1630.     gen("else if ( zzcnt>1 ) break; /* implied exit branch */\n");/* code for exiting loop */
  1631.     tab();
  1632.     makeErrorClause(q,f,max_k);
  1633.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1634.     freeBlkFsets(q);
  1635.     gen("zzcnt++;");
  1636.     if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1);
  1637.     _gen("\n");
  1638.     if ( DemandLookahead )
  1639.         if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1640.         else gen1("look(%d);\n", max_k);
  1641.     --tabs;
  1642.     if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);}
  1643.     else gen("} while ( 1 );\n");
  1644.     --BlkLevel;
  1645.     BLOCK_Tail();
  1646.     q->visited = FALSE;
  1647.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1648.     tokensRefdInBlock = savetkref;
  1649. }
  1650.  
  1651. /*
  1652.  * Generate code for a sub blk of alternatives of form:
  1653.  *
  1654.  *                   --o-G1--o--
  1655.  *                     |     ^
  1656.  *                     v    /|
  1657.  *                     o-G2-o|
  1658.  *                     |     ^
  1659.  *                     v     |
  1660.  *                   ..........
  1661.  *                     |     ^
  1662.  *                     v    /
  1663.  *                     o-Gn-o
  1664.  *
  1665.  * q points to the 1st junction of blk (upper-left).
  1666.  * q->end points to the last node (far right) in the blk.
  1667.  * Note that q->end->jtype must be 'EndBlk'.
  1668.  * The last node in every alt points to q->end.
  1669.  *
  1670.  * Generate code of the following form:
  1671.  *    if ( First(G1) ) {
  1672.  *        ...code for G1...
  1673.  *    }
  1674.  *    else if ( First(G2) ) {
  1675.  *        ...code for G2...
  1676.  *    }
  1677.  *    ...
  1678.  *    else {
  1679.  *        ...code for Gn...
  1680.  *    }
  1681.  */
  1682. void
  1683. #ifdef __USE_PROTOS
  1684. genSubBlk( Junction *q )
  1685. #else
  1686. genSubBlk( q )
  1687. Junction *q;
  1688. #endif
  1689. {
  1690.     int max_k;
  1691.     set f;
  1692.     int need_right_curly;
  1693.     set savetkref;
  1694.     savetkref = tokensRefdInBlock;
  1695.     require(q->ntype == nJunction,    "genSubBlk: not junction");
  1696.     require(q->jtype == aSubBlk,    "genSubBlk: not subblock");
  1697.  
  1698.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1699.     BLOCK_Preamble(q);
  1700.     BlkLevel++;
  1701.     f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
  1702.     if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
  1703.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1704.     freeBlkFsets(q);
  1705.     --BlkLevel;
  1706.     BLOCK_Tail();
  1707.  
  1708.     if ( q->guess )
  1709.     {
  1710.         gen("zzGUESS_DONE\n");
  1711.     }
  1712.  
  1713.     /* must duplicate if (alpha)?; one guesses (validates), the
  1714.      * second pass matches */
  1715.     if ( q->guess && analysis_point(q)==q )
  1716.     {
  1717.         if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1718.         BLOCK_Preamble(q);
  1719.         BlkLevel++;
  1720.         f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
  1721.         if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
  1722.         { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1723.         freeBlkFsets(q);
  1724.         --BlkLevel;
  1725.         BLOCK_Tail();
  1726.     }
  1727.  
  1728.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1729.     tokensRefdInBlock = savetkref;
  1730. }
  1731.  
  1732. /*
  1733.  * Generate code for a rule.
  1734.  *
  1735.  *        rule--> o-->o-Alternatives-o-->o
  1736.  * Or,
  1737.  *        rule--> o-->o-Alternative-o-->o
  1738.  *
  1739.  * The 1st junction is a RuleBlk.  The second can be a SubBlk or just a junction
  1740.  * (one alternative--no block), the last is EndRule.
  1741.  * The second to last is EndBlk if more than one alternative exists in the rule.
  1742.  *
  1743.  * To get to the init-action for a rule, we must bypass the RuleBlk,
  1744.  * and possible SubBlk.
  1745.  * Mark any init-action as generated so genBlk() does not regenerate it.
  1746.  */
  1747. void
  1748. #ifdef __USE_PROTOS
  1749. genRule( Junction *q )
  1750. #else
  1751. genRule( q )
  1752. Junction *q;
  1753. #endif
  1754. {
  1755.     int max_k;
  1756.     set follow, rk, f;
  1757.     ActionNode *a;
  1758.     RuleEntry *r;
  1759.     static int file = -1;
  1760.     int need_right_curly;
  1761.     require(q->ntype == nJunction,    "genRule: not junction");
  1762.     require(q->jtype == RuleBlk,    "genRule: not rule");
  1763.  
  1764.     r = (RuleEntry *) hash_get(Rname, q->rname);
  1765.     if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief");
  1766.     if ( q->file != file )        /* open new output file if need to */
  1767.     {
  1768.         if ( output != NULL ) fclose( output );
  1769.         output = fopen(OutMetaName(outname(FileStr[q->file])), "w");
  1770.         require(output != NULL, "genRule: can't open output file");
  1771.  
  1772.         special_fopen_actions(OutMetaName(outname(FileStr[q->file])));
  1773.  
  1774.         if ( file == -1 ) genHdr1(q->file);
  1775.         else genHdr(q->file);
  1776.         file = q->file;
  1777.     }
  1778.     DumpFuncHeader(q,r);
  1779.     tabs++;
  1780.     if ( q->ret!=NULL )
  1781.     {
  1782.         if ( HasComma(q->ret) ) {gen1("struct _rv%d _retv;\n",r->rulenum);}
  1783.         else
  1784.         {
  1785.             tab();
  1786.             DumpType(q->ret, output);
  1787.             gen(" _retv;\n");
  1788.         }
  1789.     }
  1790.  
  1791.     if ( GenLineInfo )
  1792.     {
  1793.         fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1794.     }
  1795.  
  1796.     gen("zzRULE;\n");
  1797.     if ( FoundException )
  1798.     {
  1799.         gen("int _sva=1;\n");
  1800.     }
  1801.     if ( GenCC && GenAST )
  1802.         gen("ASTBase **_astp, *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n");
  1803.     if ( GenCC ) genTokenPointers(q);
  1804.     if ( GenCC&&GenAST ) genASTPointers(q);
  1805.     if ( q->el_labels!=NULL ) genElementLabels(q->el_labels);
  1806.     if ( FoundException ) gen("int _signal=NoSignal;\n");
  1807.     if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
  1808.     if ( !GenCC ) gen("zzMake0;\n");
  1809.     if ( FoundException ) gen("*_retsignal = NoSignal;\n");
  1810.     if ( !GenCC ) gen("{\n");
  1811.  
  1812.     if ( has_guess_block_as_first_item((Junction *)q->p1) )
  1813.     {
  1814.         gen("zzGUESS_BLOCK\n");
  1815.     }
  1816.  
  1817.     /* L o o k  F o r  I n i t  A c t i o n */
  1818.     if ( ((Junction *)q->p1)->jtype == aSubBlk )
  1819.         a = findImmedAction( ((Junction *)q->p1)->p1 );
  1820.     else
  1821.         a = findImmedAction( q->p1 );    /* only one alternative in rule */
  1822.     if ( a!=NULL && !a->is_predicate )
  1823.     {
  1824.         dumpAction(a->action, output, tabs, a->file, a->line, 1);
  1825.         a->done = 1;    /* ignore action. We have already handled it */
  1826.     }
  1827.     if ( TraceGen )
  1828.         if ( GenCC ) {gen1("tracein(\"%s\");\n", q->rname);}
  1829.         else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname);
  1830.  
  1831.     BlkLevel++;
  1832.     q->visited = TRUE;                /* mark RULE as visited for FIRST/FOLLOW */
  1833.     f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly);
  1834.     if ( q->p1 != NULL )
  1835.         if ( ((Junction *)q->p1)->p2 != NULL )
  1836.             {tab(); makeErrorClause((Junction *)q->p1,f,max_k);}
  1837.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1838.     freeBlkFsets((Junction *)q->p1);
  1839.     q->visited = FALSE;
  1840.     --BlkLevel;
  1841.     if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
  1842.  
  1843.     if ( TraceGen )
  1844.         if ( GenCC ) {gen1("traceout(\"%s\");\n", q->rname);}
  1845.         else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
  1846.  
  1847.     if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n");
  1848.     /* E r r o r  R e c o v e r y */
  1849.     NewSet();
  1850.     rk = empty;
  1851.     REACH(q->end, 1, &rk, follow);
  1852.     FillSet( follow );
  1853.     set_free( follow );
  1854.  
  1855.     _gen("fail:\n");
  1856.     if ( !GenCC ) gen("zzEXIT(zztasp1);\n");
  1857.     if ( FoundGuessBlk )
  1858.            if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");}
  1859.         else gen("if ( guessing ) zzGUESS_FAIL;\n");
  1860.     if ( q->erraction!=NULL )
  1861.         dumpAction(q->erraction, output, tabs, q->file, q->line, 1);
  1862.     if ( GenCC )
  1863.     {
  1864.         gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n",
  1865.              r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
  1866.     }
  1867.     else
  1868.     {
  1869.         gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n",
  1870.              r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
  1871.     }
  1872.     gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<<setnum);
  1873.  
  1874.     if ( TraceGen )
  1875.         if ( GenCC ) {gen1("traceout(\"%s\");\n", q->rname);}
  1876.         else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
  1877.  
  1878.     if ( q->ret!=NULL ) {gen("return _retv;\n");}
  1879.     else if ( q->exceptions!=NULL ) gen("return;\n");
  1880.     if ( !GenCC ) gen("}\n");
  1881.  
  1882.     /* Gen code for exception handlers */
  1883.     if ( q->exceptions!=NULL )
  1884.     {
  1885.         gen("/* exception handlers */\n");
  1886.         dumpExceptions(q->exceptions);
  1887.         if ( !r->has_rule_exception )
  1888.         {
  1889.             _gen("_handler:\n");
  1890.             gen("zzdflthandlers(_signal,_retsignal);\n");
  1891.         }
  1892.         _gen("_adios:\n");
  1893.         if ( q->ret!=NULL ) {gen("return _retv;\n");}
  1894.         else {gen("return;\n");}
  1895.     }
  1896.     else if ( FoundException )
  1897.     {
  1898.         _gen("_handler:\n");
  1899.         gen("zzdflthandlers(_signal,_retsignal);\n");
  1900.     }
  1901.  
  1902.     tabs--;
  1903.     gen("}\n");
  1904.  
  1905.     if ( q->p2 != NULL ) {TRANS(q->p2);} /* generate code for next rule too */
  1906.     else dumpAfterActions( output );
  1907. }
  1908.  
  1909. static void
  1910. #ifdef __USE_PROTOS
  1911. DumpFuncHeader( Junction *q, RuleEntry *r )
  1912. #else
  1913. DumpFuncHeader( q, r )
  1914. Junction *q;
  1915. RuleEntry *r;
  1916. #endif
  1917. {
  1918.     /* A N S I */
  1919.     _gen("\n");
  1920.     if ( q->ret!=NULL )
  1921.     {
  1922.         if ( HasComma(q->ret) )
  1923.         {
  1924.             if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum)
  1925.             else gen1("struct _rv%d\n",r->rulenum);
  1926.         }
  1927.         else
  1928.         {
  1929.             DumpType(q->ret, output);
  1930.             gen("\n");
  1931.         }
  1932.     }
  1933.     else
  1934.     {
  1935.         _gen("void\n");
  1936.     }
  1937.     if ( !GenCC ) _gen("#ifdef __STDC__\n");
  1938.     if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname)
  1939.     else gen2("%s::%s(", CurrentClassName, q->rname);
  1940.     DumpANSIFunctionArgDef(output,q);
  1941.     _gen("\n");
  1942.  
  1943.     if ( GenCC ) {gen("{\n"); return;}
  1944.  
  1945.     /* K & R */
  1946.     gen("#else\n");
  1947.     gen2("%s%s(", RulePrefix, q->rname);
  1948.     if ( GenAST )
  1949.     {
  1950.         _gen("_root");
  1951.         if ( q->pdecl!=NULL ) _gen(",");
  1952.     }
  1953.     if ( FoundException )
  1954.     {
  1955.         if ( GenAST ) _gen(",");
  1956.         _gen("_retsignal");
  1957.         if ( q->pdecl!=NULL ) _gen(",");
  1958.     }
  1959.  
  1960.     DumpListOfParmNames( q->pdecl, output );
  1961.     gen(")\n");
  1962.     if ( GenAST ) gen("AST **_root;\n");
  1963.     if ( FoundException ) gen("int *_retsignal;\n");
  1964.     DumpOldStyleParms( q->pdecl, output );
  1965.     gen("#endif\n");
  1966.     gen("{\n");
  1967. }
  1968.  
  1969. void
  1970. #ifdef __USE_PROTOS
  1971. DumpANSIFunctionArgDef(FILE *f, Junction *q)
  1972. #else
  1973. DumpANSIFunctionArgDef(f,q)
  1974. FILE *f;
  1975. Junction *q;
  1976. #endif
  1977. {
  1978.     if ( GenAST )
  1979.     {
  1980.         if ( GenCC ) {fprintf(f,"ASTBase **_root");}
  1981.         else fprintf(f,"AST**_root");
  1982.         if ( q->pdecl!=NULL ) fprintf(f,",");
  1983.     }
  1984.     if ( FoundException )
  1985.     {
  1986.         if ( GenAST ) fprintf(f,",");
  1987.         fprintf(f,"int *_retsignal");
  1988.         if ( q->pdecl!=NULL ) fprintf(f,",");
  1989.     }
  1990.     if ( q->pdecl!=NULL ) {fprintf(f,"%s", q->pdecl);}
  1991.     else if ( !GenAST && !FoundException ) fprintf(f,"void");
  1992.     fprintf(f,")");
  1993. }
  1994.  
  1995. void
  1996. #ifdef __USE_PROTOS
  1997. genJunction( Junction *q )
  1998. #else
  1999. genJunction( q )
  2000. Junction *q;
  2001. #endif
  2002. {
  2003.     require(q->ntype == nJunction,    "genJunction: not junction");
  2004.     require(q->jtype == Generic,    "genJunction: not generic junction");
  2005.  
  2006.     if ( q->p1 != NULL ) TRANS(q->p1);
  2007.     if ( q->p2 != NULL ) TRANS(q->p2);
  2008. }
  2009.  
  2010. void
  2011. #ifdef __USE_PROTOS
  2012. genEndBlk( Junction *q )
  2013. #else
  2014. genEndBlk( q )
  2015. Junction *q;
  2016. #endif
  2017. {
  2018. }
  2019.  
  2020. void
  2021. #ifdef __USE_PROTOS
  2022. genEndRule( Junction *q )
  2023. #else
  2024. genEndRule( q )
  2025. Junction *q;
  2026. #endif
  2027. {
  2028. }
  2029.  
  2030. void
  2031. #ifdef __USE_PROTOS
  2032. genHdr( int file )
  2033. #else
  2034. genHdr( file )
  2035. int file;
  2036. #endif
  2037. {
  2038.     _gen("/*\n");
  2039.     _gen(" * A n t l r  T r a n s l a t i o n  H e a d e r\n");
  2040.     _gen(" *\n");
  2041.     _gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
  2042.     _gen(" * Purdue University Electrical Engineering\n");
  2043.     _gen(" * With AHPCRC, University of Minnesota\n");
  2044.     _gen1(" * ANTLR Version %s\n", Version);
  2045.     _gen(" */\n");
  2046.     _gen("#include <stdio.h>\n");
  2047.     _gen1("#define ANTLR_VERSION    %s\n", VersionDef);
  2048.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  2049.         _gen2("#define %s %s\n", DefaultParserName, ParserName);
  2050.        if ( strcmp(ParserName, DefaultParserName)!=0 )
  2051.         {_gen1("#include \"%s\"\n", RemapFileName);}
  2052.     if ( GenLineInfo ) _gen2(LineInfoFormatStr, 1, FileStr[file]);
  2053.     if ( GenCC ) {
  2054.         if ( UserTokenDefsFile != NULL )
  2055.             fprintf(output, "#include %s\n", UserTokenDefsFile);
  2056.         else
  2057.             fprintf(output, "#include \"%s\"\n", DefFileName);
  2058.     }
  2059.  
  2060.     if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1);
  2061.     if ( !GenCC && FoundGuessBlk )
  2062.     {
  2063.         _gen("#define ZZCAN_GUESS\n");
  2064.         _gen("#include <setjmp.h>\n");
  2065.     }
  2066.     if ( FoundException )
  2067.     {
  2068.         _gen("#define EXCEPTION_HANDLING\n");
  2069.         _gen1("#define NUM_SIGNALS %d\n", NumSignals);
  2070.     }
  2071.     if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k);
  2072.     if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n");
  2073.     if ( GenAST ) {
  2074.         if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);}
  2075.         else _gen("#include \"ast.h\"\n\n");
  2076.     }
  2077.     if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n");
  2078. #ifdef DUM
  2079.     if ( !GenCC && LexGen ) {
  2080.         _gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
  2081.     }
  2082. #endif
  2083.     /* ###WARNING: This will have to change when SetWordSize changes */
  2084.     if ( !GenCC ) _gen1("#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
  2085.     if ( !GenCC ) {_gen("#include \"antlr.h\"\n");}
  2086.     else {
  2087.         _gen1("#include \"%s\"\n", APARSER_H);
  2088.         _gen1("#include \"%s.h\"\n", CurrentClassName);
  2089.     }
  2090.     if ( !GenCC ) {
  2091.         if ( UserDefdTokens )
  2092.             {_gen1("#include %s\n", UserTokenDefsFile);}
  2093.         /* still need this one as it has the func prototypes */
  2094.         _gen1("#include \"%s\"\n", DefFileName);
  2095.     }
  2096.     /* still need this one as it defines the DLG interface */
  2097.     if ( !GenCC ) _gen("#include \"dlgdef.h\"\n");
  2098.     if ( LexGen && GenCC ) _gen1("#include \"%s\"\n", DLEXERBASE_H);
  2099.     if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName);
  2100. }
  2101.  
  2102. void
  2103. #ifdef __USE_PROTOS
  2104. genHdr1( int file )
  2105. #else
  2106. genHdr1( file )
  2107. int file;
  2108. #endif
  2109. {
  2110.     ListNode *p;
  2111.  
  2112.     genHdr(file);
  2113.     if ( GenAST )
  2114.     {
  2115.         if ( !GenCC ) {
  2116.             _gen("#include \"ast.c\"\n");
  2117.             _gen("zzASTgvars\n\n");
  2118.         }
  2119.     }
  2120.     if ( !GenCC ) _gen("ANTLR_INFO\n");
  2121.     if ( BeforeActions != NULL )
  2122.     {
  2123.         for (p = BeforeActions->next; p!=NULL; p=p->next)
  2124.         {
  2125.             UserAction *ua = (UserAction *)p->elem;
  2126.             dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
  2127.         }
  2128.     }
  2129.  
  2130.     if ( !FoundException ) return;
  2131.  
  2132.     if ( GenCC )
  2133.     {
  2134.         _gen1("\nvoid %s::\n", CurrentClassName);
  2135.         _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
  2136.         _gen("{\n");
  2137.     }
  2138.     else
  2139.     {
  2140.         _gen("\nvoid\n");
  2141.         _gen("#ifdef __STDC__\n");
  2142.         _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
  2143.         _gen("#else\n");
  2144.         _gen("zzdflthandlers( _signal, _retsignal )\n");
  2145.         _gen("int _signal;\n");
  2146.         _gen("int *_retsignal;\n");
  2147.         _gen("#endif\n");
  2148.         _gen("{\n");
  2149.     }
  2150.     tabs++;
  2151.     gen("*_retsignal = _signal;\n");
  2152.     if ( DefaultExGroup!=NULL )
  2153.     {
  2154.         dumpException(DefaultExGroup, 1);
  2155.         if ( !hasDefaultException(DefaultExGroup) )
  2156.         {
  2157.             gen("default :\n");
  2158.             tabs++;
  2159.             gen("*_retsignal = _signal;\n");
  2160.             tabs--;
  2161.             gen("}\n");
  2162.         }
  2163.     }
  2164.  
  2165.     tabs--;
  2166.     _gen("}\n\n");
  2167. }
  2168.  
  2169. void
  2170. #ifdef __USE_PROTOS
  2171. genStdPCCTSIncludeFile( FILE *f )
  2172. #else
  2173. genStdPCCTSIncludeFile( f )
  2174. FILE *f;
  2175. #endif
  2176. {
  2177.     fprintf(f,"#ifndef STDPCCTS_H\n");
  2178.     fprintf(f,"#define STDPCCTS_H\n");
  2179.     fprintf(f,"/*\n");
  2180.     fprintf(f," * %s -- P C C T S  I n c l u d e\n", stdpccts);
  2181.     fprintf(f," *\n");
  2182.     fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
  2183.     fprintf(f," * Purdue University Electrical Engineering\n");
  2184.     fprintf(f," * With AHPCRC, University of Minnesota\n");
  2185.     fprintf(f," * ANTLR Version %s\n", Version);
  2186.     fprintf(f," */\n");
  2187.     fprintf(f,"#include <stdio.h>\n");
  2188.     fprintf(f,"#define ANTLR_VERSION    %s\n", VersionDef);
  2189.     if ( GenCC )
  2190.     {
  2191.         if ( UserDefdTokens )
  2192.             fprintf(f, "#include %s\n", UserTokenDefsFile);
  2193.         else {
  2194.             fprintf(f, "#include \"%s\"\n", DefFileName);
  2195.         }
  2196.  
  2197.         fprintf(f, "#include \"%s\"\n", ATOKEN_H);
  2198.  
  2199.         if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
  2200.  
  2201.         fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H);
  2202.  
  2203.         if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k);
  2204.         if ( GenAST ) {
  2205.             fprintf(f, "#include \"%s\"\n", ASTBASE_H);
  2206.         }
  2207.         fprintf(f,"#include \"%s\"\n", APARSER_H);
  2208.         fprintf(f,"#include \"%s.h\"\n", CurrentClassName);
  2209.         if ( LexGen ) fprintf(f,"#include \"%s\"\n", DLEXERBASE_H);
  2210.         fprintf(f, "#endif\n");
  2211.         return;
  2212.     }
  2213.  
  2214.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  2215.         fprintf(f, "#define %s %s\n", DefaultParserName, ParserName);
  2216.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  2217.         fprintf(f, "#include \"%s\"\n", RemapFileName);
  2218.     if ( UserTokenDefsFile != NULL )
  2219.        fprintf(f, "#include %s\n", UserTokenDefsFile);
  2220.     if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
  2221.     if ( FoundGuessBlk )
  2222.     {
  2223.         fprintf(f,"#define ZZCAN_GUESS\n");
  2224.         fprintf(f,"#include <setjmp.h>\n");
  2225.     }
  2226.     if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k);
  2227.     if ( GenAST ) fprintf(f,"#define GENAST\n");
  2228.     if ( FoundException )
  2229.     {
  2230.         _gen("#define EXCEPTION_HANDLING\n");
  2231.         _gen1("#define NUM_SIGNALS %d\n", NumSignals);
  2232.     }
  2233.     if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n");
  2234. #ifdef DUM
  2235.     if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
  2236. #endif
  2237.     /* ###WARNING: This will have to change when SetWordSize changes */
  2238.     fprintf(f, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
  2239.     fprintf(f,"#include \"antlr.h\"\n");
  2240.     if ( GenAST ) fprintf(f,"#include \"ast.h\"\n");
  2241.     if ( UserDefdTokens )
  2242.         fprintf(f, "#include %s\n", UserTokenDefsFile);
  2243.     /* still need this one as it has the func prototypes */
  2244.     fprintf(f, "#include \"%s\"\n", DefFileName);
  2245.     /* still need this one as it defines the DLG interface */
  2246.     fprintf(f,"#include \"dlgdef.h\"\n");
  2247.     /* don't need this one unless DLG is used */
  2248.     if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName);
  2249.     fprintf(f,"#endif\n");
  2250. }
  2251.  
  2252. /* dump action 's' to file 'output' starting at "local" tab 'tabs'
  2253.    Dump line information in front of action if GenLineInfo is set
  2254.    If file == -1 then GenLineInfo is ignored.
  2255.    The user may redefine the LineInfoFormatStr to his/her liking
  2256.    most compilers will like the default, however.
  2257.  
  2258.    June '93; changed so that empty lines are left alone so that
  2259.    line information is correct for the compiler/debuggers.
  2260. */
  2261. void
  2262. #ifdef __USE_PROTOS
  2263. dumpAction( char *s, FILE *output, int tabs, int file, int line,  
  2264. int final_newline )
  2265. #else
  2266. dumpAction( s, output, tabs, file, line, final_newline )
  2267. char *s;
  2268. FILE *output;
  2269. int tabs;
  2270. int file;
  2271. int line;
  2272. int final_newline;
  2273. #endif
  2274. {
  2275.     int inDQuote, inSQuote;
  2276.     require(s!=NULL,         "dumpAction: NULL action");
  2277.     require(output!=NULL,    eMsg1("dumpAction: output FILE is NULL for %s",s));
  2278.  
  2279.     if ( GenLineInfo && file != -1 )
  2280.     {
  2281.         fprintf(output, LineInfoFormatStr, line, FileStr[file]);
  2282.     }
  2283.     PastWhiteSpace( s );
  2284.     /* don't print a tab if first non-white char is a # (preprocessor command) */
  2285.     if ( *s!='#' ) {TAB;}
  2286.     inDQuote = inSQuote = FALSE;
  2287.     while ( *s != '\0' )
  2288.     {
  2289.         if ( *s == '\\' )
  2290.         {
  2291.             fputc( *s++, output ); /* Avoid '"' Case */
  2292.             if ( *s == '\0' ) return;
  2293.             if ( *s == '\'' ) fputc( *s++, output );
  2294.             if ( *s == '\"' ) fputc( *s++, output );
  2295.         }
  2296.         if ( *s == '\'' )
  2297.         {
  2298.             if ( !inDQuote ) inSQuote = !inSQuote;
  2299.         }
  2300.         if ( *s == '"' )
  2301.         {
  2302.             if ( !inSQuote ) inDQuote = !inDQuote;
  2303.         }
  2304.         if ( *s == '\n' )
  2305.         {
  2306.             fputc('\n', output);
  2307.             s++;
  2308.             PastWhiteSpace( s );
  2309.             if ( *s == '}' )
  2310.             {
  2311.                 --tabs;
  2312.                 TAB;
  2313.                 fputc( *s++, output );
  2314.                 continue;
  2315.             }
  2316.             if ( *s == '\0' ) return;
  2317.             if ( *s != '#' )    /* #define, #endif etc.. start at col 1 */
  2318.             {
  2319.                 TAB;
  2320.             }
  2321.         }
  2322.         if ( *s == '}' && !(inSQuote || inDQuote) )
  2323.         {
  2324.             --tabs;            /* Indent one fewer */
  2325.         }
  2326.         if ( *s == '{' && !(inSQuote || inDQuote) )
  2327.         {
  2328.             tabs++;            /* Indent one more */
  2329.         }
  2330.         fputc( *s, output );
  2331.         s++;
  2332.     }
  2333.     if ( final_newline ) fputc('\n', output);
  2334. }
  2335.  
  2336. static void
  2337. #ifdef __USE_PROTOS
  2338. dumpAfterActions( FILE *output )
  2339. #else
  2340. dumpAfterActions( output )
  2341. FILE *output;
  2342. #endif
  2343. {
  2344.     ListNode *p;
  2345.     require(output!=NULL, "dumpAfterActions: output file was NULL for some reason");
  2346.     if ( AfterActions != NULL )
  2347.     {
  2348.         for (p = AfterActions->next; p!=NULL; p=p->next)
  2349.         {
  2350.             UserAction *ua = (UserAction *)p->elem;
  2351.             dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
  2352.         }
  2353.     }
  2354.     fclose( output );
  2355. }
  2356.  
  2357. /*
  2358.  * Find the next action in the stream of execution.  Do not pass
  2359.  * junctions with more than one path leaving them.
  2360.  * Only pass generic junctions.
  2361.  *
  2362.  *    Scan forward while (generic junction with p2==NULL)
  2363.  *    If we stop on an action, return ptr to the action
  2364.  *    else return NULL;
  2365.  */
  2366. static ActionNode *
  2367. #ifdef __USE_PROTOS
  2368. findImmedAction( Node *q )
  2369. #else
  2370. findImmedAction( q )
  2371. Node *q;
  2372. #endif
  2373. {
  2374.     Junction *j;
  2375.     require(q!=NULL, "findImmedAction: NULL node");
  2376.     require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node");
  2377.     
  2378.     while ( q->ntype == nJunction )
  2379.     {
  2380.         j = (Junction *)q;
  2381.         if ( j->jtype != Generic || j->p2 != NULL ) return NULL;
  2382.         q = j->p1;
  2383.         if ( q == NULL ) return NULL;
  2384.     }
  2385.     if ( q->ntype == nAction ) return (ActionNode *)q;
  2386.     return NULL;
  2387. }
  2388.  
  2389. static void
  2390. #ifdef __USE_PROTOS
  2391. dumpRetValAssign( char *retval, char *ret_def )
  2392. #else
  2393. dumpRetValAssign( retval, ret_def )
  2394. char *retval;
  2395. char *ret_def;
  2396. #endif
  2397. {
  2398.     char *q = ret_def;
  2399.     
  2400.     tab();
  2401.     while ( *retval != '\0' )
  2402.     {
  2403.         while ( isspace((*retval)) ) retval++;
  2404.         while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output);
  2405.         fprintf(output, " = _trv.");
  2406.         
  2407.         DumpNextNameInDef(&q, output);
  2408.         fputc(';', output); fputc(' ', output);
  2409.         if ( *retval == ',' ) retval++;
  2410.     }
  2411. }
  2412.  
  2413. /* This function computes the set of tokens that can possibly be seen k
  2414.  * tokens in the future from point j
  2415.  */
  2416. static set
  2417. #ifdef __USE_PROTOS
  2418. ComputeErrorSet( Junction *j, int k )
  2419. #else
  2420. ComputeErrorSet( j, k )
  2421. Junction *j;
  2422. int k;
  2423. #endif
  2424. {
  2425.     Junction *alt1;
  2426.     set a, rk, f;
  2427.     require(j->ntype==nJunction, "ComputeErrorSet: non junction passed");
  2428.  
  2429.     f = rk = empty;
  2430.     for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2)
  2431.     {
  2432.         REACH(alt1->p1, k, &rk, a);
  2433.         require(set_nil(rk), "ComputeErrorSet: rk != nil");
  2434.         set_free(rk);
  2435.         set_orin(&f, a);
  2436.         set_free(a);
  2437.     }
  2438.     return f;
  2439. }
  2440.  
  2441. static char *
  2442. #ifdef __USE_PROTOS
  2443. tokenFollowSet(TokNode *p)
  2444. #else
  2445. tokenFollowSet(p)
  2446. TokNode *p;
  2447. #endif
  2448. {
  2449.     static char buf[100];
  2450.     set rk, a;
  2451.     int n;
  2452.     rk = empty;
  2453.  
  2454.     REACH(p->next, 1, &rk, a);
  2455.     require(set_nil(rk), "rk != nil");
  2456.     set_free(rk);
  2457.     n = DefErrSet( &a, 0, NULL );
  2458.     set_free(a);
  2459.     if ( GenCC )
  2460.         sprintf(buf, "err%d", n);
  2461.     else
  2462.         sprintf(buf, "zzerr%d", n);
  2463.     return buf;
  2464. }
  2465.  
  2466. static void
  2467. #ifdef __USE_PROTOS
  2468. makeErrorClause( Junction *q, set f, int max_k )
  2469. #else
  2470. makeErrorClause( q, f, max_k )
  2471. Junction *q;
  2472. set f;
  2473. int max_k;
  2474. #endif
  2475. {
  2476.     if ( FoundException )
  2477.     {
  2478.         _gen("else {\n");
  2479.         tabs++;
  2480.         if ( FoundGuessBlk )
  2481.         {
  2482.             if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
  2483.             else gen("if ( zzguessing ) goto fail;\n");
  2484.         }
  2485.         gen("if (_sva) _signal=NoViableAlt;\n");
  2486.         gen("else _signal=NoSemViableAlt;\n");
  2487.         gen("goto _handler;\n");
  2488.         tabs--;
  2489.         gen("}\n");
  2490.         return;
  2491.     }
  2492.  
  2493.     if ( max_k == 1 )
  2494.     {
  2495.         if ( GenCC ) {_gen1("else {FAIL(1,err%d", DefErrSet(&f,1,NULL));}
  2496.         else _gen1("else {zzFAIL(1,zzerr%d", DefErrSet(&f,1,NULL))
  2497.         set_free(f);
  2498.     }
  2499.     else
  2500.     {
  2501.         int i;
  2502.         set_free(f);
  2503.         if ( GenCC ) {_gen1("else {FAIL(%d", max_k);}
  2504.         else _gen1("else {zzFAIL(%d", max_k);
  2505.         for (i=1; i<=max_k; i++)
  2506.         {
  2507.             f = ComputeErrorSet(q, i);
  2508.             if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1, NULL ));}
  2509.             else _gen1(",zzerr%d", DefErrSet( &f, 1, NULL ));
  2510.             
  2511.             set_free(f);
  2512.         }
  2513.     }
  2514.     _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n");
  2515. }
  2516.